﻿using System;
using UnityEngine;

namespace HEFramework
{
    public static class AnimatorComponentSystem
    {
        [EntitySystem]
        public class AnimatorComponentAwakeSystem : AwakeSystem<AnimatorComponent>
        {
            protected override void Awake(AnimatorComponent _self)
            {
                var gc = _self.Parent.GetChild<GameObjectComponent>();

                if (gc == null)
                {
                    return;
                }

                Animator animator = gc.GameObject.GetComponent<Animator>();

                if (animator == null)
                {
                    return;
                }

                if (animator.runtimeAnimatorController == null)
                {
                    return;
                }

                if (animator.runtimeAnimatorController.animationClips == null)
                {
                    return;
                }

                _self.Animator = animator;
                foreach (AnimationClip animationClip in animator.runtimeAnimatorController.animationClips)
                {
                    _self.AnimationClips[animationClip.name] = animationClip;
                }

                foreach (AnimatorControllerParameter animatorControllerParameter in animator.parameters)
                {
                    _self.Parameter.Add(animatorControllerParameter.name);
                }
            }
        }

        [EntitySystem]
        public class AnimatorComponentUpdateSystem : UpdateSystem<AnimatorComponent>
        {
            protected override void Update(AnimatorComponent _self)
            {
                if (_self.IsStop)
                {
                    return;
                }

                if (_self.MotionType == MotionType.None)
                {
                    return;
                }

                try
                {
                    _self.Animator.SetFloat("MotionSpeed", _self.MontionSpeed);
                    _self.Animator.SetTrigger(_self.MotionType.ToString());
                    _self.MontionSpeed = 1;
                    _self.MotionType = MotionType.None;
                }
                catch (Exception ex)
                {
                    throw new Exception($"动作播放失败: {_self.MotionType}", ex);
                }
            }
        }

        [EntitySystem]
        public class AnimatorComponentDestroySystem : DestroySystem<AnimatorComponent>
        {
            protected override void Destroy(AnimatorComponent _self)
            {
                _self.AnimationClips = null;
                _self.Parameter = null;
                _self.Animator = null;
            }
        }

        public static bool HasParameter(this AnimatorComponent _self, string _parameter)
        {
            return _self.Parameter.Contains(_parameter);
        }

        public static void PlayInTime(this AnimatorComponent _self, MotionType _motionType, float _time)
        {
            AnimationClip animationClip;
            if (!_self.AnimationClips.TryGetValue(_motionType.ToString(), out animationClip))
            {
                throw new Exception($"找不到该动作: {_motionType}");
            }

            float motionSpeed = animationClip.length / _time;
            if (motionSpeed < 0.01f || motionSpeed > 1000f)
            {
                Log.Error($"motionSpeed数值异常, {motionSpeed}, 此动作跳过");
                return;
            }

            _self.MotionType = _motionType;
            _self.MontionSpeed = motionSpeed;
        }

        public static void Play(this AnimatorComponent _self, MotionType _motionType, float _motionSpeed = 1f)
        {
            if (!_self.HasParameter(_motionType.ToString()))
            {
                return;
            }

            _self.MotionType = _motionType;
            _self.MontionSpeed = _motionSpeed;
        }

        public static float AnimationTime(this AnimatorComponent _self, MotionType _motionType)
        {
            AnimationClip animationClip;
            if (!_self.AnimationClips.TryGetValue(_motionType.ToString(), out animationClip))
            {
                throw new Exception($"找不到该动作: {_motionType}");
            }

            return animationClip.length;
        }

        public static void PauseAnimator(this AnimatorComponent _self)
        {
            if (_self.IsStop)
            {
                return;
            }

            _self.IsStop = true;

            if (_self.Animator == null)
            {
                return;
            }

            _self.StopSpeed = _self.Animator.speed;
            _self.Animator.speed = 0;
        }

        public static void RunAnimator(this AnimatorComponent _self)
        {
            if (!_self.IsStop)
            {
                return;
            }

            _self.IsStop = false;

            if (_self.Animator == null)
            {
                return;
            }

            _self.Animator.speed = _self.StopSpeed;
        }

        public static void SetBoolValue(this AnimatorComponent _self, string _name, bool _state)
        {
            if (!_self.HasParameter(_name))
            {
                return;
            }

            _self.Animator.SetBool(_name, _state);
        }

        public static void SetFloatValue(this AnimatorComponent _self, string _name, float _state)
        {
            if (!_self.HasParameter(_name))
            {
                return;
            }

            _self.Animator.SetFloat(_name, _state);
        }

        public static void SetIntValue(this AnimatorComponent _self, string _name, int _value)
        {
            if (!_self.HasParameter(_name))
            {
                return;
            }

            _self.Animator.SetInteger(_name, _value);
        }

        public static void SetTrigger(this AnimatorComponent _self, string _name)
        {
            if (!_self.HasParameter(_name))
            {
                return;
            }

            _self.Animator.SetTrigger(_name);
        }

        public static void SetAnimatorSpeed(this AnimatorComponent _self, float _speed)
        {
            _self.StopSpeed = _self.Animator.speed;
            _self.Animator.speed = _speed;
        }

        public static void ResetAnimatorSpeed(this AnimatorComponent _self)
        {
            _self.Animator.speed = _self.StopSpeed;
        }
    }
}